package com.lx.demo.b.core.filter;


import com.alibaba.dubbo.common.Constants;
import com.alibaba.dubbo.common.extension.Activate;
import com.alibaba.dubbo.rpc.*;
import com.lx.CommonResultCode;
import com.lx.Remessages;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.validator.HibernateValidator;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import java.util.Set;

/**
 * Created by lanyXP on 2020/6/23
 * 定义调用dubbo参数校验规则 dubbo服务端正常整合HibernateValidator 实现优雅操作
 * dubbo服务端如采用DTO 进行参数接收实体DTO必须实现序列化接口Serializable
 * 用户自定义了自己的参数校验Filter 在配置使用时不必要配置dubbo自带的参数校验类 以免影响效率
 * @see com.alibaba.dubbo.validation.filter.ValidationFilter
 */
@Slf4j
@Activate(group = {Constants.PROVIDER, Constants.CONSUMER}, order = 9999)
public class DubboCustomParamValidationFilter implements Filter {
    private static final Validator VALIDATOR = Validation.byProvider(HibernateValidator.class)
            .configure()
            .failFast(true)
            .buildValidatorFactory()
            .getValidator();

    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        if (!invocation.getMethodName().startsWith("$")) {
            final Object[] arguments = invocation.getArguments();
            for (Object body : arguments) {
                final Set<ConstraintViolation<Object>> validates = VALIDATOR.validate(body);
                if (validates != null && !validates.isEmpty()) {
                    ConstraintViolation<Object> next = validates.iterator().next();
                    return new RpcResult(Remessages.fail(CommonResultCode.PARAMS_VALATE_FAIL.getCode(), next.getMessage()));
                }
            }
        }
        return invoker.invoke(invocation);
    }
}